package com.wolfking.jeesite.controller;

import com.wolfking.jeesite.config.SsoConfig;
import com.wolfking.jeesite.entity.Dict;
import com.wolfking.jeesite.entity.Menu;
import com.wolfking.jeesite.entity.User;
import com.wolfking.jeesite.event.LoginEvent;
import com.wolfking.jeesite.event.LogoutEvent;
import com.wolfking.jeesite.exception.JeesiteException;
import com.wolfking.jeesite.freemarker.TemplateRenderService;
import com.wolfking.jeesite.service.DictService;
import com.wolfking.jeesite.service.MenuService;
import com.wolfking.jeesite.sso.SsoConfigService;
import com.wolfking.jeesite.sso.SsoService;
import com.wolfking.jeesite.sign.LoginUser;
import com.wolfking.jeesite.sign.Sign;
import com.wolfking.jeesite.util.CookieUtil;
import com.wolfking.jeesite.util.SignEventUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 登录的controller
 * <p>
 *
 * @author wolfking@赵伟伟
 * @mail zww199009@163.com
 * @创作日期 2017年4月19日下午5:50:23
 * @版权 归wolfking所有
 */
@Slf4j
@Controller
public class LoginController {

    @Autowired
    private DictService dictService;

    @Autowired
    private SsoConfigService ssoConfigService;

    @Autowired
    private SsoConfig ssoConfig;

    @Autowired
    private SsoService ssoService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private TemplateRenderService templateRenderService;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Sign(loginPage = true)
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(Model model, @RequestParam(required = false) String from, HttpServletRequest request,
                        HttpServletResponse response) {
        User user = ssoService.getUser();
        if (user != null) {
            String redirect;
            if (StringUtils.isBlank(from))
                redirect = ssoConfig.getRedirectWithPath("/main");
            else
                redirect = "redirect:" + from;
            log.info("目前已经登录：{}", redirect);
            return redirect;
        }
        List<Dict> themes = dictService.getByType("theme");
        model.addAttribute("themes", themes);
        String theme = CookieUtil.getCookie(request, "theme");
        if (StringUtils.isBlank(theme)) {
            CookieUtil.setCookie(request, response, "theme", "default");
            model.addAttribute("currentTheme", "默认主题");
        } else {
            boolean set = false;
            for (Dict dict : themes) {
                if (dict.getValue().equals(theme)) {
                    CookieUtil.setCookie(request, response, "theme", theme);
                    model.addAttribute("currentTheme", dict.getLabel());
                    set = true;
                    break;
                }
            }
            if (!set) {
                CookieUtil.setCookie(request, response, "theme", "default");
                model.addAttribute("currentTheme", "默认主题");
            }
        }
        model.addAttribute("from", from);
        return "sys/login";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String doLogin(Model model, HttpServletRequest request, HttpServletResponse response,
                          @RequestParam String username, @RequestParam String password, @RequestParam(required = false) String from) {
        log.info("username password is :{} {}", username, password);
        model.addAttribute("username", username);
        try {
            User login = ssoService.login(username, password);
            String tokenId = login.getTokenId();
            //发送登录事件
            try {
                eventPublisher.publishEvent(SignEventUtil.createSignEvent(request, LoginEvent.class, login.getId()));
            } catch (Exception e) {
                log.warn("", e);
            }
            // 设置登录有效时间是1天
            CookieUtil.setCookie(request, response, "tokenId", tokenId, 86400 * 10);
            String redirect;
            if (StringUtils.isBlank(from))
                redirect = ssoConfig.getRedirectWithPath("/main");
            else
                redirect = "redirect:" + from;
            log.info("登陆后跳转：{}", redirect);
            return redirect;
        } catch (Exception e) {
            log.warn("{}", e.getMessage());
            try {
                JeesiteException ex = JeesiteException.parse(e);
                model.addAttribute("message", ex.getMessage());
            } catch (Exception ee) {
                log.error("", e);
                model.addAttribute("message", "登录异常");
            }
        }
        return login(model, from, request, response);
    }

    /**
     * 用户注销
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logOut(HttpServletRequest request, HttpServletResponse response) {
        String ssoLogin = CookieUtil.getCookie(request, "sso_login");
        String tokenId = ssoService.getTokenId(request);
        String userId = "";
        if (StringUtils.isNoneBlank(tokenId)) {
            userId = ssoService.logout(tokenId);
        }
        //发送登出事件
        try {
            eventPublisher.publishEvent(SignEventUtil.createSignEvent(request, LogoutEvent.class,
                    StringUtils.isNoneBlank(userId) ? Integer.parseInt(userId) : null));
        } catch (Exception e) {
            log.warn("", e);
        }
        CookieUtil.deleteCookie(request, response, new Cookie("tokenId", ""));
        CookieUtil.deleteCookie(request, response, new Cookie("sso_login", ""));
        String ssoLogout = ssoConfigService.getSsoLogout();
        boolean redirectSsoLogout = ssoConfigService.getLogoutRedirectSsoLogout();
        if (StringUtils.isNotBlank(ssoLogout) && "true".equals(ssoLogin.trim()) && redirectSsoLogout) {
            return "redirect:" + ssoLogout;
        } else {
            return ssoConfig.getRedirectWithPath("/login");
        }
    }

    @Sign(eventName = "主页")
    @RequestMapping(value = "/main", method = RequestMethod.GET)
    public String mainPage(Model model, @LoginUser User user, HttpServletRequest request, @RequestParam(required = false) Integer id) {
        log.info("index 登录用户的tokenId is {}", ssoService.getTokenId(request));
        log.info("login user is : {}", user.getLoginName());
        List<Menu> menuList = menuService.getMainUserMenus(user.getId());
        log.info("menuList is : {}", menuList);
        if (Objects.isNull(id)) {
            String indexPageId = dictService.getSystemParameter("index_page_id", "");
            log.info("系统参数的菜单ID是 {}", indexPageId);
            if (StringUtils.isNotBlank(indexPageId)) {
                try {
                    id = Integer.parseInt(indexPageId);
                } catch (Exception e) {
                    log.warn("");
                }
            }
        }
        if (Objects.nonNull(id)) {
            Menu menu = menuService.getById(id);
            if (Objects.nonNull(menu) && StringUtils.isNotBlank(menu.getHref())) {
                String href = templateRenderService.renderTemplate(menu.getHref());
                log.info("index page href is {}", href);
                menu.setHref(href);
                model.addAttribute("menu", menu);
            }
        }
        model.addAttribute("menuList", menuList);
        return "sys/main";
    }

    @ResponseBody
    @RequestMapping(value = "/login_trace", method = RequestMethod.GET)
    public Map<String, Object> loginTrace() {
        return ssoService.loginTrace();
    }
}
